package com.salt.modules.sys.utils;

import com.google.common.collect.Lists;
import com.salt.common.service.BaseService;
import com.salt.common.utils.SpringContextHolder;
import com.salt.common.utils.StringUtils;
import com.salt.core.redis.utils.CacheUtils;
import com.salt.modules.sys.entity.*;
import com.salt.modules.sys.mapper.*;
import com.salt.modules.sys.security.util.JWTUtil;
import org.apache.commons.collections.CollectionUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.UnavailableSecurityManagerException;
import org.apache.shiro.session.InvalidSessionException;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 用户工具类
 * @author salt
 * @version 2016-12-05
 */
public class UserUtils {

	private static UserMapper userMapper = SpringContextHolder.getBean(UserMapper.class);
	private static RoleMapper roleMapper = SpringContextHolder.getBean(RoleMapper.class);
	private static MenuMapper menuMapper = SpringContextHolder.getBean(MenuMapper.class);
	private static AreaMapper areaMapper = SpringContextHolder.getBean(AreaMapper.class);
	private static OfficeMapper officeMapper = SpringContextHolder.getBean(OfficeMapper.class);
	private static DataRuleMapper dataRuleMapper = SpringContextHolder.getBean(DataRuleMapper.class);
	private static MultiTenantMapper multiTenantMapper = SpringContextHolder.getBean(MultiTenantMapper.class);

	public static final String USER_CACHE = "userCache";
	public static final String USER_CACHE_ID_ = "id_";
	public static final String USER_CACHE_LOGIN_NAME_ = "ln";
	public static final String USER_CACHE_LIST_BY_OFFICE_ID_ = "oid_";
	public static final String USER_CACHE_MOBILE = "mobile";

	public static final String CACHE_ROLE_LIST = "roleList";
	public static final String CACHE_TOP_MENU = "topMenu";
	public static final String CACHE_MENU_LIST = "menuList";
	public static final String CACHE_MENU_APP_LIST = "menuAppList";
	public static final String CACHE_ALL_MENU_LIST = "allMenuList";
	public static final String CACHE_LIKE_PARENT_IDS_MENU_LIST = "likeParentIdsMenuList";
	public static final String CACHE_DATA_RULE_LIST = "dataRuleList";
	public static final String CACHE_AREA_LIST = "areaList";
	public static final String CACHE_OFFICE_LIST = "officeList";
	public static final String CACHE_OFFICE_ALL_LIST = "officeAllList";

	public static final String CACHE_PERMISSION_MENU_LIST = "permissionMenuList";

	/**
	 * 根据ID获取用户
	 * @param id
	 * @return 取不到返回null
	 */
	public static User get(String id){
		User user = (User) CacheUtils.get(USER_CACHE, USER_CACHE_ID_ + id);
		if (user ==  null){
			user = userMapper.get(id);
			if (user == null){
				return null;
			}
			CacheUtils.put(USER_CACHE, USER_CACHE_ID_ + user.getId(), user);
			CacheUtils.put(USER_CACHE, USER_CACHE_LOGIN_NAME_ + user.getLoginName(), user);
		}
		return user;
	}

	public static String getUserNameById(String id){
		User user = get(id);
		if(user == null){
			return "";
		}else{
			return user.getName();
		}
	}


	/**
	 * 根据登录名获取用户
	 * @param loginName
	 * @return 取不到返回null
	 */
	public static User getByLoginName(String loginName){
		User user = (User)CacheUtils.get(USER_CACHE, USER_CACHE_LOGIN_NAME_ + loginName);
		if (user == null){
			user = userMapper.getByLoginName(new User(null, loginName));
			if (user == null){
				return null;
			}
			CacheUtils.put(USER_CACHE, USER_CACHE_ID_ + user.getId(), user);
			CacheUtils.put(USER_CACHE, USER_CACHE_LOGIN_NAME_ + user.getLoginName(), user);
			if (StringUtils.isNotBlank(user.getMobile())){
				CacheUtils.put(USER_CACHE, USER_CACHE_MOBILE + user.getMobile(), user);
			}
		}
		return user;
	}

	public static void updateFreeCodeClearUser(User user) {
		CacheUtils.remove(USER_CACHE, USER_CACHE_ID_ + user.getId());
		CacheUtils.remove(USER_CACHE, USER_CACHE_LOGIN_NAME_ + user.getLoginName());
		if (StringUtils.isNotBlank(user.getMobile())){
			CacheUtils.remove(USER_CACHE, USER_CACHE_LOGIN_NAME_ + user.getMobile());
		}
	}

	public static User getByMobile(String mobile) {
		User user = (User) CacheUtils.get(USER_CACHE, USER_CACHE_MOBILE + mobile);
		if (user == null) {
			user = userMapper.getByMobile(new User(null, null, mobile));
			if (user == null)
				return null;
			CacheUtils.put(USER_CACHE, USER_CACHE_ID_ + user.getId(), user);
			if (StringUtils.isNotBlank(user.getLoginName())) {
				CacheUtils.put(USER_CACHE, USER_CACHE_LOGIN_NAME_ + user.getLoginName(), user);
			}
			CacheUtils.put(USER_CACHE, USER_CACHE_MOBILE + user.getMobile(), user);
		}
		return user;
	}

	/**
	 * 清除当前用户缓存
	 */
	public static void clearCache(){
		removeCache(CACHE_ROLE_LIST);
		removeCache(CACHE_DATA_RULE_LIST);
		removeCache(CACHE_TOP_MENU);
		removeCache(CACHE_MENU_LIST);
		removeCache(CACHE_MENU_APP_LIST);
		removeCache(CACHE_ALL_MENU_LIST);
		removeCache(CACHE_LIKE_PARENT_IDS_MENU_LIST);
		removeCache(CACHE_AREA_LIST);
		removeCache(CACHE_OFFICE_LIST);
		removeCache(CACHE_OFFICE_ALL_LIST);
		removeCache(CACHE_PERMISSION_MENU_LIST);
		UserUtils.clearCache(getUser());
	}

	public static void clearUserDataCache() {
		removeCache(CACHE_ROLE_LIST);
		removeCache(CACHE_OFFICE_LIST);
		removeCache(CACHE_OFFICE_ALL_LIST);
	}


	public static void clearMenuCache() {
		removeCache(CACHE_MENU_LIST);
	}


	/**
	 * 清除指定用户缓存
	 * @param user
	 */
	public static void clearCache(User user){
		CacheUtils.remove(USER_CACHE, USER_CACHE_ID_ + user.getId());
		CacheUtils.remove(USER_CACHE, USER_CACHE_LOGIN_NAME_ + user.getLoginName());
		CacheUtils.remove(USER_CACHE, USER_CACHE_LOGIN_NAME_ + user.getOldLoginName());
		if (user.getOffice() != null && user.getOffice().getId() != null){
			CacheUtils.remove(USER_CACHE, USER_CACHE_LIST_BY_OFFICE_ID_ + user.getOffice().getId());
		}
	}

	/**
	 * 获取当前用户
	 * @return 取不到返回 new User()
	 */
	public static User getUser(){
		String token = getToken();
		if (token!=null){
			User user = getByLoginName(JWTUtil.getLoginName(token));
			if (user != null){
				return user;
			}
			return new User();
		}
		// 如果没有登录，则返回实例化空的User对象。
		return new User();
	}

	/**
	 * 获取当前用户角色列表
	 * @return
	 */
	public static List<Role> getRoleList(){
		@SuppressWarnings("unchecked")
		List<Role> roleList = (List<Role>)getCache(CACHE_ROLE_LIST);
		if (roleList == null){
			User user = getUser();
			if (user.isAdmin()){
				roleList = roleMapper.findAllList(new Role());
			}else{
				roleList = user.getRoleList();
			}
			putCache(CACHE_ROLE_LIST, roleList);
		}
		return roleList;
	}

	/**
	 * 获取平台所有的菜单
	 * @return
	 */
	/*public static List<Menu> getAllMenuList() {
		List<Menu> allMenuList = (List<Menu>)getCache(CACHE_ALL_MENU_LIST);
		if (allMenuList == null) {
			allMenuList = menuMapper.findAllList(new Menu());
			putCache(CACHE_ALL_MENU_LIST, allMenuList);
		}
		return allMenuList;
	}*/

	/**
	 * 获取平台所有的菜单
	 * @return
	 */
	public static List<Menu> getAllMenuList(Menu menu) {
		String tenant = menu.getTenant();
		String client = menu.getClient();
		List<Menu> allMenuList = (List<Menu>)getCache(CACHE_ALL_MENU_LIST);
		if (allMenuList == null) {
			if (menu.getTenantIds() != null)
				menu.setTenant(null);
			allMenuList = menuMapper.findAllList(menu);
			putCache(CACHE_ALL_MENU_LIST, allMenuList);
		}
		List<Menu> menuListByTenant = new ArrayList<>();
		if (allMenuList != null && !allMenuList.isEmpty()) {
			allMenuList.stream().forEach(m -> {
				if (tenant.equals(m.getTenant()) && client.equals(m.getClient()))
					menuListByTenant.add(m);
			});
		}
		return menuListByTenant;
	}

	/**
	 * 根据父级菜单查询所有的子级及子子级菜单
	 * @param menu
	 * @return
	 */
	/*public static List<Menu> getByParentIdsLikeMenuList(Menu menu) {
		List<Menu> menuList = (List<Menu>)getCache(CACHE_LIKE_PARENT_IDS_MENU_LIST);
		if (menuList == null) {
			menuList = menuMapper.getByParentIdsLikeUserId(menu);
			User user = getUser();
			// 给开发人员添加管理员操作权限，待开发完成后删掉
			String liXiaoId = "dd13928c8ada4ed8af0df2fe2ea8bba4"; // 李枭
			String zhangZhiYuan = "0540c5e7bf9a4c54b2b40852afeeae09"; //  张致远
			String zhaoYan = "f8956953eae849a9a58cadb85a4a403c";
			String chengfengfeng = "0adf19db75224a9aa3e502d1e21bfbb0";
			if (user.isAdmin() || liXiaoId.equals(user.getId()) || zhangZhiYuan.equals(user.getId()) || zhaoYan.equals(user.getId()) || chengfengfeng.equals(user.getId())){
				// 开发完成后，将上面删掉，将该行放开
				//if (user.isAdmin()){
				menuList = menuMapper.findAllList(menu);
			}else{
				menu.setUserId(user.getId());
				menuList = menuMapper.findByUserId(menu);
			}
			putCache(CACHE_LIKE_PARENT_IDS_MENU_LIST, menuList);
		}
		return menuList;
	}*/

	public static List<Menu> getByParentIdsLikeMenuList(Menu menu) {
		List<Menu> menuList = (List<Menu>)getCache(CACHE_LIKE_PARENT_IDS_MENU_LIST);
		if (menuList == null) {
			menuList = menuMapper.getByParentIdsLikeUserId(menu);
			putCache(CACHE_LIKE_PARENT_IDS_MENU_LIST, menuList);
		}
		return menuList;
	}

	/**
	 * 获取权限菜单，尚未区分PC端和手机端
	 * @return
	 */
	public static List<Menu> getPermissionMenuList(){
		List<Menu> permissionMenuList = (List<Menu>)getCache(CACHE_PERMISSION_MENU_LIST);
		if (permissionMenuList == null) {
			User user = getUser();
			Menu menu = new Menu();
			if (user.isAdmin()){
				permissionMenuList = menuMapper.findAllList(menu);
			} else if (AdminUtils.isAdmin()) {
				List<Admin> adminList = AdminUtils.findAdminList(user);
				List<String> adminIds = new ArrayList<>();
				if (adminList != null && !adminList.isEmpty()) {
					adminList.stream().forEach(admin -> adminIds.add(admin.getTenant()));
				}
				if (!adminIds.isEmpty()) {
					List<String> adminTenantIdList = adminIds.stream().distinct().collect(Collectors.toList());
					menu.setTenant(null);
					menu.setTenantIds(adminTenantIdList);
					permissionMenuList = menuMapper.findAllList(menu); // 管理员
				}
				List<String> tenantIds = getTenantIds(user);
				if (tenantIds != null && !tenantIds.isEmpty()) {
					if (!adminIds.isEmpty())
						tenantIds = (List<String>) CollectionUtils.subtract(tenantIds, adminIds);
					if (!tenantIds.isEmpty()) {
						menu.setTenant(null);
						menu.setTenantIds(tenantIds);
						menu.setUserId(user.getId());
						List<Menu> menuListByUserId = menuMapper.findByUserId(menu); // 其它公司根据角色用户
						permissionMenuList.addAll(menuListByUserId);
					}
				}
			} else {
				// 多租户权限
				menu.setUserId(user.getId());
				permissionMenuList = menuMapper.findByUserId(menu);
			}
			if (permissionMenuList != null && !permissionMenuList.isEmpty()) {
				List<Menu> appMenuList = permissionMenuList.stream()
						.filter(t -> Objects.equals(t.getClient(), "1"))
						.collect(Collectors.toList());
				putCache(CACHE_MENU_APP_LIST, appMenuList);
				List<Menu> pcMenuList = permissionMenuList.stream()
						.filter(t -> Objects.equals(t.getClient(), "2"))
						.collect(Collectors.toList());
				Menu defalutAppMenu = menuMapper.get("100"); // ui mac版应用商店菜单
				pcMenuList.add(defalutAppMenu);
				putCache(CACHE_MENU_LIST, pcMenuList);
			}
			putCache(CACHE_PERMISSION_MENU_LIST, permissionMenuList);
		}
		return permissionMenuList;
	}

	/**
	 * 获取当前用户授权菜单
	 * @return
	 */
	public static List<Menu> getMenuList(Menu menu){
		List<String> tenantIds = menu.getTenantIds();
		String tenant = menu.getTenant();
		String client = menu.getClient();
		List<Menu> menuList = null;
		if ("1".equals(client)) {  // 手机端
			menuList = (List<Menu>)getCache(CACHE_MENU_APP_LIST);
		} else if ("2".equals(client)) {  // PC端
			menuList = (List<Menu>)getCache(CACHE_MENU_LIST);
		}

		if (menuList == null){
			User user = getUser();
			if (user.isAdmin()){
				Menu m = new Menu();
				m.setClient(client);
				menuList = menuMapper.findAllList(m);
			} else if (AdminUtils.isAdmin(tenant)) {
				List<Admin> adminList = AdminUtils.findAdminList(user);
				List<String> adminIds = new ArrayList<>();
				if (adminList != null && !adminList.isEmpty()) {
					adminList.stream().forEach(admin -> adminIds.add(admin.getTenant()));
				}
				if (!adminIds.isEmpty()) {
					List<String> adminTenantIdList = adminIds.stream().distinct().collect(Collectors.toList());
					menu.setTenant(null);
					menu.setTenantIds(adminTenantIdList);
					menuList = menuMapper.findAllList(menu); // 管理员
				}
				if (tenantIds != null && !tenantIds.isEmpty()) {
					if (!adminIds.isEmpty())
						tenantIds = (List<String>) CollectionUtils.subtract(tenantIds, adminIds);
					if (!tenantIds.isEmpty()) {
						menu.setTenant(null);
						menu.setTenantIds(tenantIds);
						menu.setUserId(user.getId());
						List<Menu> menuListByUserId = menuMapper.findByUserId(menu); // 其它公司根据角色用户
						menuList.addAll(menuListByUserId);
					}
				}
			} else {
				menu.setUserId(user.getId());
				menuList = menuMapper.findByUserId(menu);
			}
			if ("1".equals(client)) {  // 手机端
				putCache(CACHE_MENU_APP_LIST, menuList);
			} else if ("2".equals(client)) {  // PC端
				Menu defalutAppMenu = menuMapper.get("100"); // ui mac版应用商店菜单
				menuList.add(defalutAppMenu);
				putCache(CACHE_MENU_LIST, menuList);
			}
		}
		/*List<Menu> menuListByTenant = new ArrayList<>();
		if (menuList != null && !menuList.isEmpty()) {
			menuList.stream().forEach(m -> {
				if ((tenant.equals(m.getTenant()) && client.equals(m.getClient()))
						|| "100".equals(m.getId()))
					menuListByTenant.add(m);
			});
		}
		return menuListByTenant;*/
		if (menuList != null && !menuList.isEmpty()) {
			if (StringUtils.isNotBlank(tenant)) {
				List<Menu> menuListByTenant = menuList.stream()
						.filter(m -> (tenant.equals(m.getTenant()) && client.equals(m.getClient())) || "100".equals(m.getId()))
						.collect(Collectors.toList());
				return menuListByTenant;
			} else {
				List<Menu> menus = menuList.stream()
						.filter(m -> client.equals(m.getClient()) || "100".equals(m.getId()))
						.collect(Collectors.toList());
				return menus;
			}
		}
		return new ArrayList<>();
	}

	/**
	 * 获取当前用户授权数据权限
	 * @return
	 */
	public static List<DataRule> getDataRuleList(){
		@SuppressWarnings("unchecked")
		List<DataRule> dataRuleList = (List<DataRule>)getCache(CACHE_DATA_RULE_LIST);
		if (dataRuleList == null){
			User user = getUser();
			if (user.isAdmin()){
				dataRuleList = Lists.newArrayList();
			} else {
				dataRuleList = dataRuleMapper.findByUserId(user);
			}
			putCache(CACHE_DATA_RULE_LIST, dataRuleList);
		}
		return dataRuleList;
	}

	/**
	 * 获取当前用户授权菜单
	 * @return
	 */
	public static Menu getTopMenu() {
		Menu topMenu = (Menu) getCache(CACHE_TOP_MENU);
		if (topMenu == null) {
			topMenu = menuMapper.get("1");
			putCache(CACHE_TOP_MENU, topMenu);
		}
		return  topMenu;
	}
	/**
	 * 获取当前用户授权的区域
	 * @return
	 */
	public static List<Area> getAreaList(){
		@SuppressWarnings("unchecked")
		List<Area> areaList = (List<Area>)getCache(CACHE_AREA_LIST);
		if (areaList == null){
			areaList = areaMapper.findAllList(new Area());
			putCache(CACHE_AREA_LIST, areaList);
		}
		return areaList;
	}

	/**
	 * 获取当前用户有权限访问的部门
	 * @return
	 */
	public static List<Office> getOfficeList(){
		@SuppressWarnings("unchecked")
		List<Office> officeList = (List<Office>)getCache(CACHE_OFFICE_LIST);
		if (officeList == null){
			User user = getUser();
			if (user.isAdmin()){
				officeList = officeMapper.findAllList(new Office());
			} else {
				Office office = new Office();
				BaseService.dataRuleFilter(office);
				officeList = officeMapper.findList(office);
			}
			putCache(CACHE_OFFICE_LIST, officeList);
		}
		return officeList;
	}

	/**
	 * 获取当前用户有权限访问的部门
	 * @return
	 */
	public static List<Office> getOfficeAllList(){
		@SuppressWarnings("unchecked")
		List<Office> officeList = (List<Office>)getCache(CACHE_OFFICE_ALL_LIST);
		if (officeList == null){
			officeList = officeMapper.findAllList(new Office());
		}
		return officeList;
	}

	/**
	 * 获取授权主要对象
	 */
	public static Subject getSubject(){
		return SecurityUtils.getSubject();
	}

	/**
	 * 获取当前登录者对象
	 */
	public static String getToken(){
		try{
			Subject subject = SecurityUtils.getSubject();
			Object token = subject.getPrincipal();
			if (token != null){
				return token.toString();
			}
//			subject.logout();
		}catch (UnavailableSecurityManagerException e) {

		}catch (InvalidSessionException e){

		}
		return null;
	}

	public static Session getSession(){
		try{
			Subject subject = SecurityUtils.getSubject();
			Session session = subject.getSession(false);
			if (session == null){
				session = subject.getSession();
			}
			System.out.println("sessionId: " + session.getId());

			if (session != null){
				return session;
			}
//			subject.logout();
		}catch (InvalidSessionException e){

		}
		return null;
	}

	// ============== User Cache ==============

	public static Object getCache(String key) {
		return getCache(key, null);
	}

	public static Object getCache(String key, Object defaultValue) {
//		Object obj = getCacheMap().get(key);
		Object obj = getSession().getAttribute(key);
		return obj==null?defaultValue:obj;
	}

	public static void putCache(String key, Object value) {
//		getCacheMap().put(key, value);
		getSession().setAttribute(key, value);
	}

	public static void removeCache(String key) {
//		getCacheMap().remove(key);
		getSession().removeAttribute(key);
	}

	public static String getTime(Date date){
		StringBuffer time = new StringBuffer();
        Date date2 = new Date();
        long temp = date2.getTime() - date.getTime();
        long days = temp / 1000 / 3600/24;                //相差小时数
        if(days>0){
        	time.append(days+"天");
        }
        long temp1 = temp % (1000 * 3600*24);
        long hours = temp1 / 1000 / 3600;                //相差小时数
        if(days>0 || hours>0){
        	time.append(hours+"小时");
        }
        long temp2 = temp1 % (1000 * 3600);
        long mins = temp2 / 1000 / 60;                    //相差分钟数
        time.append(mins + "分钟");
        return  time.toString();
	}




	/**
	 * 导出Excel调用,根据姓名转换为ID
	 */
	public static User getByUserName(String name){
		User u = new User();
		u.setName(name);
		List<User> list = userMapper.findList(u);
		if(list.size()>0){
			return list.get(0);
		}else{
			return new User();
		}
	}
	/**
	 * 导出Excel使用，根据名字转换为id
	 */
	public static Office getByOfficeName(String name){
		Office o = new Office();
		o.setName(name);
		List<Office> list = officeMapper.findList(o);
		if(list.size()>0){
			return list.get(0);
		}else{
			return new Office();
		}
	}
	/**
	 * 导出Excel使用，根据名字转换为id
	 */
	public static Area getByAreaName(String name){
		Area a = new Area();
		a.setName(name);
		List<Area> list = areaMapper.findList(a);
		if(list.size()>0){
			return list.get(0);
		}else{
			return new Area();
		}
	}


	public static boolean hasPermission(String permission){
		return SecurityUtils.getSubject().isPermitted(permission);
	}

	public static List<String> getTenantIds(User user) {
		MultiTenant multiTenant = multiTenantMapper.find(new MultiTenant(user));;
		if (multiTenant != null) {
			String[] split = multiTenant.getTenants().split(",");
			List<String> tenantIds = Arrays.asList(split);
			List<String> ids = tenantIds.stream().distinct().collect(Collectors.toList());
			return ids;
		}
		return null;
	}

}
